package org.graysblog.dinojs.rhino;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Properties;

import org.mozilla.javascript.*;
import org.graysblog.dinojs.runner.*;

public class RhinoScriptRunner {
	
	/* This class is where the actual running of script through rhino begins */

	public void RunFile(Properties AppProps, String AppPath) {
		
		String AppName = AppProps.getProperty(Constants.ApplicationTitleKey);
		
		/* Get app source from file */
		
		String AppSource = null;
		String AppDepends = null;
		
		try {
			
			StringBuffer fileData = new StringBuffer(1000);
			
			BufferedReader reader = new BufferedReader(new FileReader(AppPath+AppProps.getProperty(Constants.ApplicationSourceKey)));
			
			char[] buf = new char[1024];
			
			int numRead = 0;
			
			while((numRead=reader.read(buf)) != -1){
	            fileData.append(buf, 0, numRead);
	        }
	        reader.close();
	        
	        AppSource = fileData.toString();
	        
	        /* Now get apps framework TODO: CLEANUP ALL THIS */
	        StringBuffer fileDataDepends = new StringBuffer(1000);
			
			BufferedReader readerDepends = new BufferedReader(new FileReader(AppPath+AppProps.getProperty(Constants.ApplicationDependsKey)));
			
			char[] bufDepends = new char[1024];
			
			int numReadDepends = 0;
			
			while((numReadDepends=readerDepends.read(bufDepends)) != -1){
	            fileDataDepends.append(bufDepends, 0, numReadDepends);
	        }
	        readerDepends.close();
	        
	        AppDepends = fileDataDepends.toString();
	        
		} catch (Exception e) {
			System.out.println("Error reading app source file");
		}
		
		this.RunScript(AppSource, AppName, AppDepends);
	}
	
	public void RunScript(String Script, String AppName, String AppDepends) {
		
		Context cx = Context.enter();
		
		try {
			
			Scriptable scope = cx.initStandardObjects();
			
			/* Eval depends */
			cx.evaluateString(scope, AppDepends, AppName, 1, null);
			
			/* Eval app */
			cx.evaluateString(scope, Script, AppName, 1, null);
			
			/* Attempt to run main function */
			Object mainFunction = scope.get("main", scope);
			
			
			/* Call a method to initialize scope */
			this.AddJavaObjects(scope);
			
			
			
			if (!(mainFunction instanceof Function)) {
				System.out.println("Warning: Application does not implement main function");
			} else {
				Object FunctionArgs[] = null;
				
				Function f = (Function)mainFunction;
				
				Object result = f.call(cx, scope, scope, FunctionArgs);
			}
			
		} catch (Exception e) {
			System.out.println("Application encountered an error! "+e.getMessage());
		}
		
		Context.exit();
		
	}
	
	public void AddJavaObjects(Scriptable scope) {
		
		/* Add the output object (Java) */
		Object JSOut = Context.javaToJS(System.out, scope);
		ScriptableObject.putProperty(scope, "out", JSOut);
		
	}
}
